import { defineStore } from 'pinia'
import { getAllTreeDict, getDictList, getDictNameList, getTreeList } from '@/framework/apis/dictionary'
import { getAllNodes, isEmpty, isNotEmpty } from '@/framework/utils/common'
import { getConfig } from '@/framework/apis/parameter'
import { Ref } from 'vue'

const requestMap = new Map()

export const useParameterStore = defineStore('parameterStore', {
  state: () => {
    return {
      map: new Map() // 用于判断请求中 headers 字段中的 Authorization
    }
  },
  actions: {
    async getParameter(parameterName: string) {
      const result = this.map.get(parameterName)
      if (isNotEmpty(result)) {
        return result
      }
      getConfig(parameterName).then((res) => {
        this.map.set(parameterName, res.payload)
        return res.payload
      })
    }
  },
  getters: {}
})

export const useDictStore = defineStore('dictStore', {
  state: () => {
    return {
      map: new Map(),
      allDict: [] as Array<{ value: string; label: string }>
    }
  },
  actions: {
    async getDict(dictName: string, target?: Ref<any>, preProcess?: (data: any) => any) {
      const result = this.map.get(dictName)
      if (isNotEmpty(result)) {
        if (target) target.value = result.data || []
        return result.data
      }
      if (requestMap.has(dictName)) {
        return requestMap.get(dictName)
      }
      const request = getDictList(dictName).then((res) => {
        let payload = res.payload
        if (preProcess) {
          payload = preProcess(res.payload)
        }
        const valueMap = new Map()
        const labelMap = new Map()

        payload.forEach((data: any) => {
          valueMap.set(data.value, data.label)
          labelMap.set(data.label, data.value)
          data.text = data.label
        })
        this.map.set(dictName, { data: payload, valueMap, labelMap })
        if (target) target.value = payload || []
        return payload || []
      })
      requestMap.set(dictName, request)
      return await request
    },
    async getLabelByValue(dictName: string, value: number | string) {
      const dict = this.map.get(dictName)
      if (isEmpty(dict)) {
        return await this.getDict(dictName).then(() => {
          return this.getLabel(dictName, value)
        })
      } else {
        return this.getLabel(dictName, value)
      }
    },
    async getValueByLabel(dictName: string, label: number | string) {
      let dict = this.map.get(dictName)
      if (isEmpty(dict)) {
        return await this.getDict(dictName).then(() => {
          dict = this.map.get(dictName)
          return dict.labelMap.get(label)
        })
      } else {
        return dict.labelMap.get(label)
      }
    },
    getLabel(dictName: string, value: number | string) {
      if (isEmpty(value)) return ''
      const dictArray = value.toString().split(',')
      const display = [] as Array<string>
      dictArray.forEach((item: any) => {
        display.push(this.map.get(dictName).valueMap.get(item))
      })
      return display.join(',')
    },
    getValue(dictName: string, label: number | string) {
      return this.map.get(dictName).labelMap.get(label)
    },
    async getAllDict(dictName: string) {
      if (isEmpty(this.allDict)) {
        return await getDictNameList({ name: dictName }).then((res) => {
          this.allDict = res.payload || []
          return this.allDict
        })
      } else {
        if (isEmpty(dictName)) {
          return this.allDict
        } else {
          return this.allDict.filter((dict) => dict.value.indexOf(dictName) !== -1)
        }
      }
    },
    getMap(dictName: string) {
      return this.map.get(dictName)
    },
    getIndex(dictName: string, property: string, target: string) {
      const optionList = this.map.get(dictName).data
      return optionList.findIndex((item: any) => item[property] === target)
    }
  },
  getters: {}
})

export const useTreeStore = defineStore('treeStore', {
  state: () => {
    return {
      map: new Map(),
      allDict: [] as Array<{ value: string; label: string }>
    }
  },
  actions: {
    async getTree(dictName: string, target?: Ref<any>) {
      const result = this.map.get(dictName)
      if (isNotEmpty(result)) {
        if (target) target.value = result.data || []
        return result.data
      }
      return await getTreeList(dictName).then((res) => {
        const valueMap = new Map()
        const labelMap = new Map()
        getAllNodes(res.payload, (item: any) => {
          valueMap.set(item.value.toString(), item.label)
          labelMap.set(item.label, item.value)
          item.text = item.label
          item.id = item.value
        })
        this.map.set(dictName, { data: res.payload, valueMap, labelMap })
        return res.payload
      })
    },
    getLabel(dictName: string, value: number | string) {
      if (isEmpty(value)) return ''
      const dictArray = value.toString().split(',')
      const display = [] as Array<string>
      dictArray.forEach((item: any) => {
        display.push(this.map.get(dictName).valueMap.get(item))
      })
      return display.join(',')
    },
    getValue(dictName: string, label: number | string) {
      return this.map.get(dictName).labelMap.get(label)
    },
    async getAllDict() {
      if (isEmpty(this.allDict)) {
        return await getAllTreeDict().then((res: any) => {
          this.allDict = res.payload || []
          return this.allDict
        })
      } else {
        return this.allDict
      }
    },
    async getLabelByValue(dictName: string, value: number | string) {
      const dict = this.map.get(dictName)
      if (isEmpty(dict)) {
        return await this.getTree(dictName).then(() => {
          return this.getLabel(dictName, value)
        })
      } else {
        return this.getLabel(dictName, value)
      }
    },
    async getValueByLabel(dictName: string, label: number | string) {
      let dict = this.map.get(dictName)
      if (isEmpty(dict)) {
        return await this.getTree(dictName).then(() => {
          dict = this.map.get(dictName)
          return dict.labelMap.get(label)
        })
      } else {
        return dict.labelMap.get(label)
      }
    },
  },
  getters: {}
})

export const usePersistentDataStore = defineStore('persistentDataStore', {
  state: () => {
    return {
      map: new Map()
    }
  },
  actions: {
    async getPersistentData(dataName: string, func?: () => Promise<any>) {
      const data = this.map.get(dataName)
      if (data) return data
      if (!func) return
      return func().then((res) => {
        this.map.set(dataName, res)
        return res
      })
    }
  }
})
